Windows
Windows are platform-specific data structures through which documents display themselves. This section discusses how to use OpenDoc window objects (which are basically wrappers for those structures) regardless of which platform you are developing for. Some information specific to the Mac OS is also provided where appropriate. For more detailed Mac OS programming information on windows, see Inside Macintosh: Macintosh Toolbox Essentials.Creating and Using Windows
The OpenDoc classODWindow
is a wrapper for a pointer to a platform-specific window structure. For some operations, your part editor must retrieve the window pointer from theODWindow
object and use the platform's facilities. In most cases, however, the interface toODWindow
provides the capability you need for interacting with your windows.The Window State Object
There is a single instantiated window state object (classODWindowState
) for each OpenDoc session. The window state consists of a list of the currently existing window objects. You can access all open windows in a session through the window state.The document shell and dispatcher use the window state to pass events to parts so that they can activate themselves, handle user input, and adjust their menus as necessary. A part may be displayed in any number of frames, in any window of a document. The dispatcher uses the window state to make sure that it passes events to the correct part, no matter what window encloses the active frame and how many other frames the part has.
Normally, your part editor calls the window state only when it creates new windows, when it needs access to a particular window, and when it needs access to the base menu bar object.
If for some reason your part needs access to all windows, you can create an
ODWindowIterator
object, which gives you access to all windows referenced by the window state.Creating and Registering a Window
To receive events in a window, you generally must create an OpenDoc window object for it. (You may not be able to create an OpenDoc window for a Mac OS modal dialog box, but you can pass an event filter routine to it and therefore receive Mac OS events.) Windows in OpenDoc are created and maintained through the window-state object, which you access through the session object.You first create a window with platform-specific calls; you then call the window state object to create an OpenDoc window object describing the platform-specific window. You call either of two methods:
A window has an is-root property. If the property is true, the window is a root window, which is the same as a document window. The root part of a root window is the root part of its document, and the document cannot close as long as the root window is open. If a window's is-root property is false, the window may be either a part window that has been opened from a source frame within a root window, or it may be a dialog box, palette, or other utility window. OpenDoc permits multiple document windows for a single document, as long as the root part provides a user interface to support this feature. The document shell closes a document when the document's last document window (root window) is closed.
- You call the
RegisterWindow
method ofODWindowState
when you create a window that is not a root window or that has not yet been written to storage.- You call the call the
RegisterWindowForFrame
method ofODWindowState
when you create a root window from a previously stored root frame. (RegisterWindowForFrame
takes fewer parameters thanRegisterWindow
because the frame passed in with the method already contains some of the needed information.)
Windows also have a should-save property that, if true, specifies that the state of the window is saved persistently after the window closes. Usually, only document windows should be marked as should-save.
The creator of a window can specify the view type and presentation of the root frame, the frame that displays the root part. The view type specifies whether the root part should draw itself as an icon, and the presentation specifies what kind of appearance the part content should have if not drawn as an icon. View type and presentation are suggestions to the part editor that draws within that frame. View type and presentation are described in more detail in the section "Defining General Display Characteristics".
OpenDoc assumes that each window has a single canvas, which is attached to the window's root facet, the facet created for the root frame. On the Mac OS platform, the root frame in the window has the same shape as the window's content region: it includes window scroll bars but excludes the window's resize box, if present.
Your part should create windows as invisible and then make them visible as described in "Opening a Window"
Allocating Window Memory Efficiently
On the Mac OS platform, you can save on the total amount of memory required for your part's document by allocating your windows in system memory rather than in the application heap. If you do so, however, you are responsible for disposing of the platform-specific window structure yourself. Follow these steps:
- Allocate the platform-specific window in temporary memory, by using calls such as this:
WindowPtr myWindow = GetNewCWindow(kWINDID,((Ptr)ODNewPtr(sizeof(WindowRecord)), (WindowPtr)-1L);
ODNewPtr
is a function of the ODMemory utility library, supplied with OpenDoc; when called in this manner it allocates the pointer in temporary memory.)
- When registering the window and retrieving the OpenDoc window object, pass a value of
kODFalse
for theshouldDispose
parameter ofRegisterWindow
orRegisterWindowForFrame
. This value tells OpenDoc not to dispose of the underlying platform-specific window.- Add code to your
DisplayFrameClosed
andDisplayFrameRemoved
methods to dispose of the platform-specific window if the frame being removed or closed is a root frame.
Opening a Window
After creating a window, your part editor typically makes calls to these three methods, in this order:
- the window's
Open
method, which creates the root facet- the window's
Show
method, which makes the window visible- the window's
Select
method, which brings the window to the front
Window IDs
Your part editor should not maintain references toODWindow
objects for accessing OpenDoc windows, because the document shell or the window state object can close a window and invalidate the reference. Instead, the window state assigns window IDs that are valid for the length of a session. Use the window'sGetID
method to get the ID of a window when you create it, and then pass that ID to the window state'sAcquireWindow
method for subsequent access to the window.Closing a Window
If your part editor needs to close a window programmatically, it calls the window'sCloseAndRemove
method. That method closes the window, releases the window object and disposes of the platform-specific window structure, deletes the root facet and canvas, and removes the root frame from the document. It also makes any necessary platform-specific calls to dispose of the window itself.Storing and Retrieving Window Characteristics
Whenever a document is saved, OpenDoc writes certain information into a storage unit referenced from the storage unit of the window's root frame. The window's bounding rectangle, title, and other characteristics are saved in a property of typekODPropWindowProperties
in that storage unit.When you create a root window, you retrieve that information from the stored frame and use it to specify the platform-specific window's characteristics. You can use functions of the WinUtils utility library (provided with OpenDoc) to extract that information, or you can access the frame's storage unit directly. The
kODPropWindowProperties
property contains a persistent reference to another storage unit, which (for Mac OS windows) contains the properties listed in Table 6-1.
- Making sure a window is onscreen
- If your part is a root part that recreates a previously stored document window, you must make sure that the window is visible onscreen. Your document may have been moved from one system to another with a different monitor configuration or size. You may need to move or resize the window to fit its new environment.
![]()
The Open Method of Your Part Editor
Opening your part means creating a window for it and displaying it in the window. You have to open a window only if your part is to be the root part of that window.Your part itself initiates the opening of a window when the user selects the View in Window command from the Edit menu (see "View in Window"), and when it creates its own dialog boxes. Otherwise, your part opens a window only when your part's
Open
method is called. This is the interface to theOpen
method:
ODID Open(in ODFrame frame);TheOpen
method is called in these circumstances.
In your implementation of
- When your part is initially created--when it has no previously stored frame or window information--OpenDoc calls your part's
Open
method and passes a null value ofkODNULL
for theframe
parameter.- When your part is an embedded part whose frame is selected, and the user chooses the Open Selection command from the Document menu, your part's containing part calls your part's
Open
method and passes a reference to the selected frame in theframe
parameter.- When your part is the root part of a document being opened, OpenDoc calls your part's
Open
method and passes a reference to the root frame in theframe
parameter.
Open
, you can take steps similar to the following, depending on the circumstances under which it was called.
- If you are creating an initial window (
frame
= null), skip this step and
go to step 2.
- If you are opening a frame into a part window (
frame
= an embedded frame), check whether the window already exists. If you have created the part window previously and saved its window ID, pass that ID to theAcquireWindow
method of the window state object. If the method returns a valid window, bring the window to the front and exit. If the window does not yet exist, go to step 2.- If you are opening a stored document into a window (
frame
= a root frame), read in the saved window data from the storage unit of the frame passed to the method (see "Storing and Retrieving Window Characteristics").
- Create a platform-specific window and register it with the window state object, as described in the section "Creating and Registering a Window".
- If you are opening a stored document into a window, apply the stored characteristics to the platform-specific window. Call the window state object's
RegisterWindowForFrame
method.- If you are opening a frame into a window or creating an initial window, apply your default characteristics to the platform-specific window. Call the window state object's
RegisterWindow
method.
- Get the window's window ID and save it for future reference.
- Open and bring the window to the front, as described in "Opening a Window". If you are opening a stored document into a window, skip this step because there may be more than one window to open and OpenDoc determines which window is to be frontmost.
- Note
- You are not absolutely required to open a window when your
Open
method is called. Your part does whatever is appropriate, given its nature and the conditions under which the method is called. For example, if your part is a very simple sound player, it might simply play its sound and never create a window.![]()
Handling Window Events
To receive events in the windows that it creates, your part must create anODWindow
object for each platform-specific window it uses, including dialog boxes (except for modal dialog boxes; see "Modal Dialog Boxes").The document shell handles most Mac OS window events outside of the content region--for example, events in the title bar or resize box. Nevertheless, the OpenDoc dispatcher first sends a
kODEvtWindow
event to the root part. If the part editor of the root part wishes to override the action that the document shell would otherwise take, the root part can intercept and act on the event. In situations such as zooming, in which the window content might affect the action to be taken, the root part should intercept and handle the event.Table 6-2 lists the window events that a root part can intercept and handle. These event types are passed in the
message
field of the event structure.If your part handles a window event, its
HandleEvent
method must return true. If it does not handle an event, itsHandleEvent
method must return false so that the document shell can handle the event.Zooming
On platforms that support window zooming, the root part should handle the events kODMDInZoomIn and kODMDInZoomOut and define the appropriate window size. The document shell cannot know the appropriate window-size limits for zooming in or out. Your part can handle the zoom-in and zoom-out events by using platform-specific functions to adjust the window shape appropriately, and then calling theAdjustWindowShape
method of the window. (Your part will subsequently receive calls to itsFrameShapeChanged
andGeometryChanged
methods, notifying it that its frame and facet shapes have been changed accordingly.)Note that the new window size might trigger a frame negotiation, and it may also require the root part to create or delete facets.
Resizing
The document shell usually resizes windows, although the root part can intercept and handle the event (kODMDInGrow). The document shell relies on default size limits for windows, so if your part allows--for example--very small window sizes, it may have to intercept this event and handle the resizing itself.When a window is resized, the active part does not change, but the part editor for the root frame is informed of the resizing through calls by OpenDoc to its s
FrameShapeChanged
andGeometryChanged
methods. The root part can then do any necessary invalidation and subsequent redrawing, including creation of new facets if embedded parts have become visible because of the resizing.Closing
The document shell handles a mouse click in the close box of a window or user selection of the Close menu item (or its keyboard equivalent). The document shell closes the window, after which the window cannot be reopened. How-
ever, if the part editor of the root part wishes merely to hide its window rather than close it (for example, if it is a palette), the part editor can intercept this event (kODMDInGoAway) and call theHide
method of the window.If the window is a document window and is the only one open for that document, the document shell closes the document.
If your part editor needs to close a window programmatically, it can call the window's
CloseAndRemove
method. The window is closed and the window object is released.Dragging
The document shell handles some platform-specific window-moving actions, such as dragging of a window by its title bar. No event handling is required of the window's root part, although the root part can intercept and handle this event (kODMDInDrag) if it needs to constrain the movement of the window for some reason.Parts in other windows may need to be updated because of the window's move; they receive update events as appropriate.
Modal Dialog Boxes
When your part editor displays a Mac OS modal dialog box or alert box, it does not need to create anODWindow
object, as with a regular window. However, it should still request the modal focus (using its own display frame as the modal-focus owner), and it can still receive Mac OS events by providing an event filter.In addition, your part must ensure that Mac OS floating windows are properly deactivated. To do so, your part must deactivate the front window before displaying a modal dialog box and it must reactivate the front window after dismissing it.
Your part can, as an alternative to handling a dialog box through the Mac OS
ModalDialog
orAlert
function, create and register its own dialog window, request the modal focus for the window's root frame, and handle the dialog box without using either of those Dialog Manager routines.Acquiring and Relinquishing the Modal Focus
A frame displaying a modal dialog box should own the modal focus, a focus type that exists to constrain certain events.For example, a mouse click outside the frame that has the modal focus still goes to that frame. If your part's frame has the modal focus and the user clicks outside the frame, your part's
HandleEvent
method is called and passed a facet ofkODNULL
. The method should check for a null facet in this situation and either alert the user with a beep or dismiss the dialog box, as appropriate.A click in a frame embedded within the frame that has the modal focus goes to the embedded frame. This behavior may facilitate the construction of dialog boxes and other controls from multiple parts.
Your part obtains and relinquishes the modal focus as it does other foci; see "Requesting Foci" and "Relinquishing Foci".
In general, your part should not be willing to relinquish the modal focus on request. If your part is displaying a modal dialog box, you probably do not want any other modal dialog box to be displayed at the same time. To make sure that your part retains the modal focus, your part editor's
BeginRelinquishFocus
method should returnkODFalse
if the requested focus iskODModalFocus
and the proposed new owner of the focus is not one of your own display frames.When you have finished displaying a modal dialog box, you can directly transfer it to its previous owner by calling the arbitrator's
TransferFocus
method, as noted in "Handling a Simple Modal Dialog Box"Event Filters
With Mac OS modal dialog boxes, your part editor's dialog-box event filter controls which events you receive while a dialog box or alert box is displayed. To pass received null events, update events, and activate events on to OpenDoc or other windows for handling, your event filter can send them to the OpenDoc dispatcher by calling itsDispatch
method.Your event filter should not pass other events, such as mouse events, to the dispatcher.
Handling a Simple Modal Dialog Box
To display a simple Mac OS modal dialog box or alert box, you can take these steps:
By always saving and restoring the owner of the modal focus, your part can use this approach for nested modal dialog boxes, such as a dialog box that is built from several embedded parts.
- Get a reference to the frame that currently owns the modal focus by calling the arbitrator's
GetFocusOwner
method. Request the modal focus from the arbitrator, using itsRequestFocus
method. If you obtain the focus, proceed.- Install your dialog event filter function.
- Create the dialog box, using a Dialog Manager function such as
GetNewDialog
or a utility function such asODGetNewDialog
(from the DlogUtil utility library provided with OpenDoc). One advantage of usingODGetNewDialog
is that it positions the dialog box in relation to your part's document window, rather than to any part windows that may be open.- To handle Mac OS floating windows properly, deactivate the currently active window and any associated floating windows by calling the
DeactivateFrontWindows
method of the window state object.- Handle the dialog box with a Dialog Manager call such as
ModalDialog
. Act on the results and, when you finish, dispose of the dialog box with a Dialog Manager call such asDisposeDialog
.- Reactivate the previously active window (to restore floating windows) by calling the window state's
ActivateFrontWindows
method.- Remove your dialog event filter function.
- Restore the modal focus to its previous owner by calling the arbitrator's
TransferFocus
method.
Handling a Movable Modal Dialog Box
In OpenDoc, to implement a full-featured Mac OS movable modal dialog box--that is, one that allows process switching--you must create a window object (ODWindow
) to contain it. To display the dialog box, you can take these steps:
To make sure you dismiss the movable modal dialog box at the right time, you can take actions such as these when you receive a mouse-down event in the dialog box:
- Use platform-specific methods to create the structures for the dialog box.
- Create a window object, using the window state's
RegisterWindow
method. Give it properties appropriate for your modal dialog box, such as nonpersistent and floating.- Request the modal focus for the root frame of the dialog window.
- Adjust menus as necessary for the presence of the dialog box.
- Call the
Open
,Show
, andSelect
methods of the modal dialog window.- Handle events in the dialog box through your normal event-handling mechanism.
- Determine whether the event applies to your dialog box and, if so, what item the user selected.
- If the user has chosen to close the dialog box, relinquish the modal focus and call the window's
CloseAndRemove
method to delete the window and its root frame.- Re-enable any menus or menu items that you disabled for display of the dialog box.
- Note
- It is also possible to create a modal dialog box that is movable but does not support process switching. To do so, use a filter function and other functions in the utility library DlogUtil provided with OpenDoc.
![]()
Modeless Dialog Boxes
Modeless dialog boxes are more like regular windows than modal dialog boxes are. They can be activated and deactivated, and they need not be dismissed for your part to become active and editable.Showing the Dialog Box
To display a modeless dialog box in OpenDoc, you must create a window object (ODWindow
) to contain it. To display the dialog box, you can take steps such as these:
- In case the dialog window already exists, try to get a reference to it by passing its ID (previously stored in your part) to the window state's
AcquireWindow
method. If it does not yet exist, create the platform-specific structures for the dialog box and create a window object with the window state'sRegisterWindow
method. Call the window'sOpen
method.- Call the window's
Show
andSelect
methods to make it visible and active.- If you do not already have the window ID of the dialog window, get it by calling the window's
GetID
method. Save it for use in step 1 the next time the user chooses the action that brings up the modeless dialog box.
Closing the Dialog Box
When the user clicks the close box of a modeless dialog box, you may hide the dialog window rather than close it, so that it is not destroyed. This is an optimization that allows you to quickly redisplay the dialog box.In your part's
HandleEvent
method, you can respond in this general way to a mouse click in a window's close box:
- From the frame or facet passed to
HandleEvent
, obtain information that can identify the window. For example, get a reference to the window object in which the event occurred (by calling the facet'sGetWindow
method), or examine the frame's presentation or part info data for identifying characteristics.- Compare that information to stored information that defines your modeless dialog box. For example, get a reference to your modeless dialog's window object (by passing its ID to the window state's
AcquireWindow
method), or check a stored value that defines your modeless dialog's presentation.- If the two are the same, hide the window instead of closing it.
Hiding a Dialog Box When Deactivating a Frame
When your part is deactivated, it should hide any of its modeless dialog boxes.When your part relinquishes the selection focus, it can get a reference to the dialog window (by passing its ID to the window state's
AcquireWindow
method), call the window'sIsShown
method to see if it is currently being shown, and then save that shown state and hide the window.When your part reacquires the selection focus, it can retrieve a reference to the dialog window by passing its ID to the window state's
AcquireWindow
method. Then, if the dialog window had been visible at deactivation, your part can once again show it.
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help